package com.zmn.oms.zmn.business.impl.work.autoflow.state;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.manager.mq.constant.MqTopicConsts;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.work.erp.OrderAccountInfoListBService;
import com.zmn.oms.common.constant.MessageQueueTagConsts;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.RedisKeyConsts;
import com.zmn.oms.common.dto.OmsOperator;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.work.OperatePermissionVO;
import com.zmn.oms.zmn.aop.OrderWorkLogUtils;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.state.WorkAutoFlowBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.financework.ZsNormalAccountWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.financework.ZsNormalFinanceWorkBService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author sunlife
 * @date:2021/7/22 4:29 下午
 * description: 自动流转-算账节点
 */
@Slf4j
@Service("flowAccountBService")
public class FlowAccountBServiceImpl<T> implements WorkAutoFlowBService<T> {

    @Autowired
    ZsOrderWorkOperatePermissionBService zsOrderWorkOperatePermissionBService;
    @Autowired
    OrderAccountInfoListBService orderAccountInfoListBService;
    @Autowired
    ZsNormalFinanceWorkBService zsNormalFinanceWorkBService;
    @Autowired
    OrderLogBService orderLogBService;

    @Resource
    RedisManager redisManager;

    @Resource
    ZmnMQSender zmnMQSender;

    @Autowired
    ZsNormalAccountWorkBService zsNormalAccountWorkBService;

    // 自动算账延时时间，默认5分钟
    @NacosValue(value = "${order.autoaccount.delay.time:300}", autoRefreshed = true) // 自动算账延时时间，默认5分钟
    Integer ORDER_AUTOACCOUNT_DELAY_TIME;

    @Override
    public ResultDTO<T> condition(OrderWork orderWork) {
        ResultDTO resultDTO ;

        OperatePermissionVO permissionVO = zsOrderWorkOperatePermissionBService.getOperatePermission(orderWork, OrderConsts.ORDER_OP_TYPE_ACCOUNT, GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        if (permissionVO.getCanOperate()) {
            try {
                zsNormalAccountWorkBService.verifyOrderAmount(orderWork);
            } catch (OmsBaseException e) {
                log.error(String.format("[%s]校验自动算账失败", orderWork.getWorkId()), e);
                addAccountFailLog(orderWork, 1, e.getMessage());
                return ResultDTO.fail(e.getMessage());
            }
            resultDTO = ResultDTO.success(orderWork);
        } else {
            log.info("[{}]校验自动算账失败:{}", orderWork.getWorkId(), JSON.toJSONString(permissionVO));
            resultDTO = ResultDTO.fail(permissionVO.getMsg());
        }

        return resultDTO;
    }

    @Override
    public void execute(T t) {
        OrderWork orderWork = (OrderWork)t;

        String redisKey = String.format(RedisKeyConsts.AUTO_ACCOUNT_LOCK_KEY, orderWork.getWorkId());
        String value = String.format("%s-%s", orderWork.getOrderId(), orderWork.getWorkId());
        log.info("{}延迟算账 设置自动算账锁：key:{}", orderWork.getWorkId(), redisKey);
        redisManager.setex(redisKey, value, ORDER_AUTOACCOUNT_DELAY_TIME);

        String key = String.format("%s-%s", orderWork.getOrderId(), DateUtil.getNowTimestamp());
        JSONObject jb = new JSONObject();
        jb.put("orderId", orderWork.getOrderId());
        jb.put("workId", orderWork.getWorkId());
        String content = jb.toJSONString();

        log.info("{}延迟算账 发送延时消息：key:{}", orderWork.getWorkId(), key);
        zmnMQSender.sendWithStartDeliverTime(MqTopicConsts.ZMN_TOPIC_OMS, MessageQueueTagConsts.ORDER_DELAY_ACCOUNT, key, content, DateUtil.getNowTimestampMillis() + ORDER_AUTOACCOUNT_DELAY_TIME * 1000);
    }


    private void addAccountFailLog (OrderWork orderWork, Integer failModule, String failReason) {

        OmsOperator operator = new OmsOperator();
        operator.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        operator.setOperator("系统");
        operator.setOperatorId((long)GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        operator.setOrderId(orderWork.getOrderId());
        operator.setWorkId(orderWork.getWorkId());

        OrderLog orderLog = new OrderLog();

        // 算账失败原因
        StringBuilder sb = new StringBuilder();
        sb.append("-算账结果：失败；\n");
        sb.append("-失败缘由：\n");
        if (Objects.equals(failModule, 1)) {
            sb.append("- - 工单类型缘由：").append(failReason).append(";");
        } else if (Objects.equals(failModule, 2)) {
            sb.append("- - ERP类型缘由：").append(failReason).append(";");
        }

        orderLog.setContent(sb.toString());

        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_ACCOUNT);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_ACCOUNT));
        OrderWorkLogUtils.processOrderLogOperater(orderLog, operator);
        OrderWorkLogUtils.processOrderLogStatus(orderLog, orderWork, operator);

        orderLog.setCreateTime(DateUtil.getNow());
        orderLogBService.save(orderLog);
    }

}
